﻿using System;
using System.Net;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Communication.Base;
using UtilZ.Dotnet.Ex.Communication.Net.Base;

namespace UtilZ.Dotnet.Ex.Communication.Net.Udp
{
    /// <summary>
    /// UDP客户端初始化参数
    /// </summary>
    public class NetUdpClientInitPara : ClientInitParaAbs
    {
        /// <summary>
        /// 用于接收数据的本地EndPoint
        /// </summary>
        public EndPoint LocalEndPoint { get; private set; } = null;

        /// <summary>
        /// 用于接收数据的远端EndPoint,当不为null时在接收数据前Socket会先调用Connect连接到该远端EndPoint
        /// </summary>
        public EndPoint RemoteEndPoint { get; set; } = null;

        /// <summary>
        /// 使用的IP协议类型
        /// </summary>
        public InterNetworkType InterNetwork { get; set; } = InterNetworkType.All;

        /// <summary>
        /// 接收线程名称
        /// </summary>
        public string ReceiveThreadName { get; set; } = null;

        /// <summary>
        /// 传输模式
        /// </summary>
        public UDPTransferMode Transfer { get; set; } = UDPTransferMode.Unicast;

        /// <summary>
        /// 组播模式
        /// </summary>
        public MulticastMode Multicast { get; set; } = MulticastMode.Send;

        /// <summary>
        /// 组播地址
        /// </summary>
        public IPAddress MulticastIPAddress { get; set; } = null;

        /// <summary>
        /// 级播数据包传输距离.TTL=1表示数据包只能在本地网络传播
        /// </summary>
        public int Ttl { get; set; } = 1;

        /// <summary>
        /// 发送超时时长,单位:毫秒.大于0有效,小于等于0使用默认值
        /// </summary>
        public int SendMillisecondsTimeout { get; set; } = System.Threading.Timeout.Infinite;

        /// <summary>
        /// 接收超时时长,单位:毫秒.大于0有效,小于等于0使用默认值
        /// </summary>
        public int ReceiveMillisecondsTimeout { get; set; } = System.Threading.Timeout.Infinite;

        /// <summary>
        /// 是否接收数据[true:接收数据;false:只发送数据]
        /// </summary>
        public bool ReceiveData { get; set; } = true;

        private int _receiveBufferSize = NetHelper.UDP_PACKAGE_MAX;
        /// <summary>
        /// 接收数据缓冲区大小,默认为一个MTU
        /// </summary>
        public int ReceiveBufferSize
        {
            get { return _receiveBufferSize; }
            set
            {
                if (value <= 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), "单次接收数据包不能小于等于0");
                }

                _receiveBufferSize = value;
            }
        }

        private int _sendBufferSize = NetHelper.UDP_PACKAGE_MAX;
        /// <summary>
        /// 发送数据缓冲区大小,默认为一个MTU
        /// </summary>
        public int SendBufferSize
        {
            get { return _sendBufferSize; }
            set
            {
                if (value <= 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), "发送缓存不能小于等于0");
                }

                _sendBufferSize = value;
            }
        }

        private int _asyncReceiveStackDepth = 1000;
        /// <summary>
        /// 异步接收数据堆栈深度,该决定在大数据传输时每接收多次数据切换一次线程,以避免堆栈溢出.太小切换线程过于频繁,太大则会溢出.
        /// </summary>
        public int AsyncReceiveStackDepth
        {
            get { return _asyncReceiveStackDepth; }
            set
            {
                if (value < 10)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), "异步接收数据堆栈深度不能小于10");
                }

                if (value > 10000)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), $"异步接收数据堆栈深度不能大于1000000");
                }

                _asyncReceiveStackDepth = value;
            }
        }


        /// <summary>
        /// udp数据发送最小间隔,单位:100纳秒.小于等于0无间隔
        /// </summary>
        public int SendInterval100NS { get; set; } = 10000;

        private int _reconnectIntervalMilliseconds = 1000;
        /// <summary>
        /// 主动连接断开后，重连间隔,默认1000毫秒
        /// </summary>
        public int ReconnectIntervalMilliseconds
        {
            get { return _reconnectIntervalMilliseconds; }
            set
            {
                if (value < 1)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), "重连接间隔不能小于等1毫秒");
                }

                _reconnectIntervalMilliseconds = value;
            }
        }




        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="unpacker">分包器</param>
        /// <param name="localEndPoint">接收EndPoint</param>
        /// <exception cref="ArgumentNullException">dataOutput或receiveEndPoint为null将抛出异常</exception>
        public NetUdpClientInitPara(IUnpacker unpacker, EndPoint localEndPoint)
            : base(unpacker)
        {
            if (localEndPoint == null)
            {
                throw new ArgumentNullException(nameof(localEndPoint));
            }

            this.LocalEndPoint = localEndPoint;
        }
    }

    /// <summary>
    /// 组播模式
    /// </summary>
    public enum MulticastMode
    {
        /// <summary>
        /// 发送组播数据
        /// </summary>
        Send,

        /// <summary>
        ///  接收组播数据
        /// </summary>
        Receive,

    }

    /// <summary>
    /// udp传输模式
    /// </summary>
    public enum UDPTransferMode
    {
        /// <summary>
        /// 单播
        /// </summary>
        Unicast,

        /// <summary>
        /// 组播
        /// </summary>
        Multicast,

        /// <summary>
        ///  广播
        /// </summary>
        Broadcast,

    }
}
